﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Security.Cryptography;

namespace MyLibrary.Security
{
    /// <summary>
    /// 文件的一些安全操作
    /// </summary>
    public class FileSecurity
    {
        public FileSecurity()
        {

        }

        /// <summary>
        /// 得到文件的MD5值
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <exception cref="FileNotFoundException"></exception>
        /// <returns>MD5字符串</returns>
        public static string GetFileMD5(string filePath)
        {
            if (!File.Exists(filePath)) throw new FileNotFoundException("指定的文件找不到");

            Stream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
            MD5 md5 = new MD5CryptoServiceProvider();

            byte[] buf = md5.ComputeHash(fileStream);
            StringBuilder sb = new StringBuilder();
            for (int length = 0; length < buf.Length; length++)
                sb.Append(String.Format("{0:X2}", buf[length]));
            fileStream.Close();

            return sb.ToString();
        }

        /// <summary>
        /// 得到文件的SHA1值
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <exception cref="FileNotFoundException"></exception>
        /// <returns>SHA1字符串</returns>
        public static string GetFileSHA1(string filePath)
        {
            if (!File.Exists(filePath)) throw new FileNotFoundException("指定的文件找不到");

            Stream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
            SHA1 sha1 = new SHA1CryptoServiceProvider();

            byte[] buf = sha1.ComputeHash(fileStream);
            StringBuilder sb = new StringBuilder();
            for (int length = 0; length < buf.Length; length++)
                sb.Append(String.Format("{0:X2}", buf[length]));
            fileStream.Close();

            return sb.ToString();
        }
    }

    public class RSAProvider
    {
        #region 构造函数
        public RSAProvider()
        {

        }
        #endregion

        #region 公共方法

        /// <summary>
        /// 得到RSA密钥
        /// </summary>
        /// <param name="xmlKeys">包含私钥的XML格式</param>
        /// <param name="xmlPublicKey">只包含公钥的XML格式</param>
        public void RSAKey(out string xmlKeys, out string xmlPublicKey)
        {
            try
            {
                RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
                xmlKeys = rsa.ToXmlString(true);
                xmlPublicKey = rsa.ToXmlString(false);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        #region 字符串的加密解密
        /// <summary>
        /// 使用RSA进行加密
        /// </summary>
        /// <param name="xmlPublicKey">公钥</param>
        /// <param name="encryptString">需要加密的字符串</param>
        /// <returns>加密结果</returns>
        /// <exception cref="CryptographicException"></exception>
        /// <exception cref="ArgumentException"></exception>
        public string RSAEncrypt(string xmlPublicKey, string encryptString)
        {
            byte[] planTextArray;
            byte[] cypherTextArray;
            string result;
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();

            try
            {
                rsa.FromXmlString(xmlPublicKey);
                planTextArray = new UnicodeEncoding().GetBytes(encryptString);
                cypherTextArray = rsa.Encrypt(planTextArray, false);
                result = Convert.ToBase64String(cypherTextArray);
                return result;
            }
            catch (CryptographicException cex)
            {
                throw cex;
            }
            catch (ArgumentException aex)
            {
                throw aex;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                rsa.Clear();
            }
        }

        /// <summary>
        /// 解密RAS字符串
        /// </summary>
        /// <param name="xmlPrivateKey">私钥</param>
        /// <param name="decryptString">要解密的字符串</param>
        /// <returns>解密结果</returns>
        /// <exception cref="CryptographicException"></exception>
        /// <exception cref="ArgumentException"></exception>
        public string RSADecrypt(string xmlPrivateKey, string decryptString)
        {
            byte[] plainTextArray;
            byte[] decryptTextArray;
            string result;
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();

            try
            {
                rsa.FromXmlString(xmlPrivateKey);
                plainTextArray = Convert.FromBase64String(decryptString);
                decryptTextArray = rsa.Decrypt(plainTextArray, false);
                result = new UnicodeEncoding().GetString(decryptTextArray);
                return result;
            }
            catch (CryptographicException cex)
            {
                throw cex;
            }
            catch (ArgumentException aex)
            {
                throw aex;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                rsa.Clear();
            }
        }
        #endregion

        #region 获取Hash描述
        public string GetHashReturnString(string source)
        {
            if (String.IsNullOrEmpty(source)) throw new ArgumentNullException("source");

            byte[] buffer;
            byte[] hashData;
            HashAlgorithm md5 = HashAlgorithm.Create("MD5");
            buffer = Encoding.GetEncoding("GB2312").GetBytes(source);
            hashData = md5.ComputeHash(buffer);

            return Convert.ToBase64String(hashData);
        }

        public byte[] GetHashReturnByte(FileStream fileStream)
        {
            if (fileStream == null) throw new ArgumentNullException("fileStream");

            byte[] hashData;
            HashAlgorithm md5 = HashAlgorithm.Create("MD5");
            hashData = md5.ComputeHash(fileStream);
            fileStream.Close();
            return hashData;
        }

        public string GetHashReturnString(FileStream fileStream)
        {
            if (fileStream == null) throw new ArgumentNullException("fileStream");

            byte[] hashData;
            hashData = GetHashReturnByte(fileStream);
            return Convert.ToBase64String(hashData);
        }

        public byte[] GetHashReturnByte(string filePath)
        {
            if (String.IsNullOrEmpty(filePath)) throw new ArgumentNullException("filePath");
            if (!File.Exists(filePath)) throw new FileNotFoundException("文件未找到");

            FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
            return GetHashReturnByte(fs);
        }
        #endregion

        #region 进行RSA签名
        /// <summary>
        /// RAS签名
        /// </summary>
        /// <param name="privateKey">私钥</param>
        /// <param name="hashbytesignature">要签名的数据</param>
        /// <returns>签名后的数据</returns>
        public byte[] SignatureFormatterReturnByte(string privateKey, byte[] hashbytesignature)
        {
            if (String.IsNullOrEmpty(privateKey)) throw new ArgumentNullException("privateKey");

            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            try
            {
                rsa.FromXmlString(privateKey);
                RSAPKCS1SignatureFormatter rsaFormatter = new RSAPKCS1SignatureFormatter(rsa);
                rsaFormatter.SetHashAlgorithm("MD5");

                return rsaFormatter.CreateSignature(hashbytesignature);
            }
            catch (CryptographicException cex)
            {
                throw cex;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                rsa.Clear();

            }
        }

        /// <summary>
        /// RAS签名
        /// </summary>
        /// <param name="privateKey">私钥</param>
        /// <param name="hashstringsignature">要签名的数据</param>
        /// <returns>签名后的数据</returns>
        private byte[] SignatureFormatterReturnByte(string privateKey, string hashstringsignature)
        {
            if (String.IsNullOrEmpty(hashstringsignature)) throw new ArgumentNullException("hashstringsignature");

            try
            {
                byte[] hashbytesignature = Convert.FromBase64String(hashstringsignature);
                return SignatureFormatterReturnByte(privateKey, hashbytesignature);
            }
            catch (FormatException fex)
            {
                throw fex;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// RAS签名
        /// </summary>
        /// <param name="privateKey">私钥</param>
        /// <param name="hashbytesignature">要签名的数据</param>
        /// <returns>签名后的数据</returns>
        public string SignatureFormatterReturnString(string privateKey, byte[] hashbytesignature)
        {
            byte[] signatureData = SignatureFormatterReturnByte(privateKey, hashbytesignature);
            return Convert.ToBase64String(signatureData);
        }

        /// <summary>
        /// RAS签名
        /// </summary>
        /// <param name="privateKey">私钥</param>
        /// <param name="hashstringsignature">要签名的数据</param>
        /// <returns>签名后的数据</returns>
        public string SignatureFormatterReturnString(string privateKey, string hashstringsignature)
        {
            byte[] signatureData = SignatureFormatterReturnByte(privateKey, hashstringsignature);
            return Convert.ToBase64String(signatureData);
        }
        #endregion

        #region RSA签名验证
        /// <summary>
        /// 进行签名验证
        /// </summary>
        /// <param name="publicKey">公钥</param>
        /// <param name="hashbyteDeformatter">验证值</param>
        /// <param name="deformatterData">验证数据</param>
        /// <returns>验证结果</returns>
        public bool SignatureDeformatter(string publicKey, byte[] hashbyteDeformatter, byte[] deformatterData)
        {
            if (String.IsNullOrEmpty(publicKey)) throw new ArgumentNullException("publicKey");

            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();

            try
            {
                rsa.FromXmlString(publicKey);
                RSAPKCS1SignatureDeformatter rsaDeformatter = new RSAPKCS1SignatureDeformatter(rsa);
                rsaDeformatter.SetHashAlgorithm("MD5");

                return rsaDeformatter.VerifySignature(hashbyteDeformatter, deformatterData);
            }
            catch (ArgumentNullException aex)
            {
                throw aex;
            }
            catch (CryptographicUnexpectedOperationException cuoex)
            {
                throw cuoex;
            }
            finally
            {
                rsa.Clear();
            }
        }

        /// <summary>
        /// 进行签名验证
        /// </summary>
        /// <param name="publicKey">公钥</param>
        /// <param name="hashstringDeformatter">验证值</param>
        /// <param name="deformatterData">验证数据</param>
        /// <returns>验证结果</returns>
        public bool SignatureDeformatter(string publicKey, string hashstringDeformatter, byte[] deformatterData)
        {
            if (String.IsNullOrEmpty(hashstringDeformatter)) throw new ArgumentNullException("hashstringDeformatter");

            try
            {
                byte[] hashbyteDeformatter = Convert.FromBase64String(hashstringDeformatter);
                return SignatureDeformatter(publicKey, hashbyteDeformatter, deformatterData);
            }
            catch (FormatException fex)
            {
                throw fex;
            }
        }

        /// <summary>
        /// 进行签名验证
        /// </summary>
        /// <param name="publicKey">公钥</param>
        /// <param name="hashbyteDeformatter">验证值</param>
        /// <param name="deformatterData">验证数据</param>
        /// <returns>验证结果</returns>
        public bool SignatureDeformatter(string publicKey, byte[] hashbyteDeformatter, string deformatterData)
        {
            if (String.IsNullOrEmpty(deformatterData)) throw new ArgumentNullException("deformatterData");

            try
            {
                byte[] deformatterDataByte = Convert.FromBase64String(deformatterData);
                return SignatureDeformatter(publicKey, hashbyteDeformatter, deformatterDataByte);
            }
            catch (FormatException fex)
            {
                throw fex;
            }
        }

        /// <summary>
        /// 进行签名验证
        /// </summary>
        /// <param name="publicKey">公钥</param>
        /// <param name="hashstringDeformatter">验证值</param>
        /// <param name="deformatterDataString">验证数据</param>
        /// <returns>验证结果</returns>
        public bool SignatureDeformatter(string publicKey, string hashstringDeformatter, string deformatterDataString)
        {
            if (String.IsNullOrEmpty(hashstringDeformatter)) throw new ArgumentNullException("hashstringDeformatter");

            try
            {
                byte[] hashbyteDeformatter = Convert.FromBase64String(hashstringDeformatter);
                byte[] deformatterData = Convert.FromBase64String(deformatterDataString);
                return SignatureDeformatter(publicKey, hashbyteDeformatter, deformatterData);
            }
            catch (FormatException fex)
            {
                throw fex;
            }
        }
        #endregion

        #endregion
    }
}
